Screens & Widgets topic

Screens & Widgets

The presentation layer is organized by feature area under lib/presentation/screens/. Navigation uses GoRouter with shell routes for persistent chrome.

Routing

The route table is declared in lib/config/routes.dart. Key patterns:

  • Named routes for every destination (/, /domains, /tutor, /review, /lesson/:id, /org, /settings/:section, …).
  • Auth guards via a redirect that inspects authStateProvider — unauthenticated users hit /auth/login, authenticated but onboarding-incomplete users hit /onboarding/<step>.
  • Shell routes wrap the post-auth tree in OrgShellScaffold, which owns the bottom nav / side rail and the AppBar. Routes that live outside the shell (auth, onboarding, lesson full-screen) declare themselves at the top level.
  • Deep links route into the same tree via Uri parsing — push notifications and OAuth redirects land directly on the right screen.

Screen categories

presentation/screens/
├── admin_onboarding/   Org admin 4-step setup wizard
├── auth/               Login, signup, MFA, password reset
├── backoffice/         Platform-admin-only views
├── domains/            Curriculum domain list + detail
├── goals/              Learning goals
├── home/               Landing screen with recent activity
├── lesson/             The core learning loop (Socratic + quiz + review)
├── notes/              User notes
├── onboarding/         5-step first-connection flow
├── org/                Organization admin screens
├── progress/           Progress dashboards (mastery, XP, streaks)
├── review/             Spaced-repetition review queue
├── settings/           User + org settings
├── setup/              BYO Supabase bootstrap (Management API)
└── tutor/              Free-form Socratic dialogue

Responsive layout

OrgShellScaffold swaps navigation primitives based on viewport width:

  • < 800 px — bottom NavigationBar (mobile / narrow web).
  • ≥ 800 px — side NavigationRail (tablet / desktop / wide web).

The viewport threshold is exported as a constant so pages can mirror it for their own responsive choices.

Key reusable widgets

Widget Purpose
web_content_frame.dart Centers + max-widths content on web so the app doesn't stretch across 4K screens. The most-imported widget in the codebase.
role_gate.dart Conditional render based on entitlement lookups. RoleGate(roles: [Role.admin], child: …).
notification_bell.dart AppBar bell icon with unread badge. Watches notificationProvider.
app_mode_toggle.dart Switch between learner and admin modes (the AppBar control shown in org mode).

Testing patterns

Widget tests live in test/presentation/ and use alchemist for golden-file comparisons (tagged golden). Integration tests (test/integration/, tagged integration) run against a local Supabase and exercise the full stack — see test/integration/ for the datasource-level test suite pattern.

Classes

OrgDetailScaffold Screens & Widgets
Shared scaffold for /org/:orgId/<sub> detail screens that aren't part of the five shell destinations (Dashboard, Members, Assignments, Analytics, Settings). Renders an AppBar with the platform back button and, on narrow viewports, the same bottom NavigationBar as OrgShellScaffold so the user can escape to any of the main destinations in one tap.
OrgShellScaffold Screens & Widgets
Responsive shell for admin/manager org mode. Mirrors the personal ScaffoldWithNavBar layout but routes to /org/:orgId/* destinations.
RoleGate Screens & Widgets
Conditionally renders child based on the current user's org role.
WebContentFrame Screens & Widgets
Constrains content width on desktop while passing through on mobile.